package com.zsy.oauth2.service.impl;

import com.alibaba.fastjson.JSON;
import com.zsy.base.bean.DemoResult;
import com.zsy.oauth2.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.Cookie;
import java.io.IOException;
import java.net.URI;
import java.util.Map;

@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Value("${auth.ttl}")
    private long ttl;
    @Value("${spring.application.name}")
    private String springApplicationName;

    private static URI authorUri=null;

    /**登陆服务
     * @Author zhaoshouyun
     * @Description
     * @Date 2020-04-17 05:36
     * @Param username 用户名
     * @Param password 密码
     * @Param clientId clientID
     * @Param clientSecret secret
     * @return com.zsy.base.bean.DemoResult
     **/
    @Override
    public DemoResult login(String username, String password, String clientId, String clientSecret) {
       if (authorUri == null) {
           //1.申请令牌
           ServiceInstance serviceInstance = loadBalancerClient.choose(springApplicationName);
           URI uri = serviceInstance.getUri();
           authorUri = uri;
       }
        String url=authorUri+"/oauth/token";

        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type","password");
        body.add("username",username);
        body.add("password",password);
        log.info("{}----请求token相关参数：{}",username, JSON.toJSONString(body));
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        headers.add("Authorization",this.getHttpBasic(clientId,clientSecret));
        HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers);

        restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if (response.getRawStatusCode()!=400 && response.getRawStatusCode()!=401){
                    super.handleError(response);
                }
            }
        });

        ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
        Map map = responseEntity.getBody();
        log.info("{}----请求token结果：{}",username, map);
            //  if (map == null || map.get("access_token") == null || map.get("refresh_token") == null || map.get("jti") == null){
        if (map == null || map.get("access_token") == null || map.get("refresh_token") == null ){
            //申请令牌失败
            return DemoResult.FAIL("申请令牌失败");
        }
        return DemoResult.SUCCESS(map);
        //2.封装结果数据
       /* AuthToken authToken = new AuthToken();
        authToken.setAccessToken((String) map.get("access_token"));
        authToken.setRefreshToken((String) map.get("refresh_token"));
        authToken.setJti((String)map.get("jti"));*/


        //3.将jti作为redis中的key,将jwt作为redis中的value进行数据的存放
     //   stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);
      //  return authToken;
    }

    /**
     * @param refreshToken
     * @param clientId
     * @param clientSecret
     * @return com.zsy.base.bean.DemoResult
     * @Author zhaoshouyun
     * @Description 刷新token
     * @Date 2020-04-27 03:13
     * @Param refreshToken
     * @Param clientId
     * @Param clientSecret
     */
    @Override
    public DemoResult refreshToken(String refreshToken, String clientId, String clientSecret) {
        MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
        formData.add("client_id", clientId);
        formData.add("client_secret", clientSecret);
        formData.add("grant_type", "refresh_token");
        formData.add("refresh_token", refreshToken);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        String url=authorUri+"/oauth/token";
        Map map = restTemplate.exchange(url, HttpMethod.POST,
                    new HttpEntity<MultiValueMap<String, String>>(formData, headers), Map.class).getBody();
        log.info("{}---请求刷新token结果：{}",clientId, map);
        //  if (map == null || map.get("access_token") == null || map.get("refresh_token") == null || map.get("jti") == null){
        if (map == null || map.get("access_token") == null || map.get("refresh_token") == null ){
            //申请令牌失败
            return DemoResult.FAIL("刷新token失败,refreshToken格式非法或已失效");
        }
        return DemoResult.SUCCESS(map);
    }

    private String getHttpBasic(String clientId, String clientSecret) {
        String value = clientId+":"+clientSecret;
        byte[] encode = Base64Utils.encode(value.getBytes());
        return "Basic "+new String(encode);
    }
}
